'use strict'
console.log(new Date().getFullYear()); //获取系统日期中的年份

// 注意方法中this的指代 在一个方法内部，this是一个特殊变量，它始终指向当前对象
function getAge() {
    let y = new Date().getFullYear();
    return y - this.birth;
}

let xiaoming = {
    name: '小明',
    birth: 1990,
    age: getAge
};

xiaoming.age(); // 25, 正常结果
//getAge(); // NaN
/*
    如果以对象的方法形式调用，比如xiaoming.age()，该函数的this指向被调用的对象，也就是xiaoming，这是符合我们预期的。
    如果单独调用函数，比如getAge()，此时，该函数的this指向全局对象，也就是window
    ECMA决定，在strict模式下让函数的this指向undefined,在非strict模式下，this指向全局对象，也就是window
   */

// 每个函数自带的apply()方法
// 要指定函数的this指向哪个对象，可以用函数本身的apply方法，它接收两个参数，
// 第一个参数就是需要绑定的this变量，第二个参数是Array，表示函数本身的参数。
//getAge().apply(xiaoming,[]); //25,this指向xiaoming, 参数为空

//和apply()类似的方法call()
//apply()把参数打包成Array再传入
//call()把参数按顺序传入
//比如调用Math.max(3, 5, 4)，分别用apply()和call()实现如下
Math.max.apply(null, [3, 5, 4]); // 5
Math.max.call(null, 3, 5, 4); // 5

//装饰器
//javaScript的所有对象都是动态的，即使内置的函数，我们也可以重新指向新的函数。
/*
* 现在假定我们想统计一下代码一共调用了多少次parseInt()，可以把所有的调用都找出来，然后手动加上count += 1，
* 不过这样做太傻了。最佳方案是用我们自己的函数替换掉默认的parseInt()
* */
'use strict';

let count = 0;
let oldParseInt = parseInt; // 保存原函数

window.parseInt = function () {
    count += 1;
    return oldParseInt.apply(null, arguments); // 调用原函数
};

// 测试:
parseInt('10');
parseInt('20');
parseInt('30');
console.log('count = ' + count); // 3

//高阶函数
// +--- JavaScript的函数其实都指向某个变量。既然变量可以指向函数，函数的参数能接收变量，那么一个函数就可以接收另一个函数作为参数，
// 这种函数就称之为高阶函数。
// 编写高阶函数，就是让函数的参数能够接收别的函数
// let arr = [1,3,5,7,9];
let arr = [2,3];
console.log(arr.reduce(function (x,y) {
    return x * 10 + y;
})); //数组若只有一个元素，reduce()会默认把数组的唯一元素作为初始值

// 想办法把一个字符串13579先变成Array——[1, 3, 5, 7, 9]，
// 再利用reduce()就可以写出一个把字符串转换为Number的函数。不能使用内置parseInt()
function string2int(s) {
    
    return 0;
}
